import { execSync } from 'child_process';
import { Command } from 'commander';
import cpFile from 'cp-file';
import { glob } from 'glob';
import { writeFileSync } from 'fs';
import { normalize, resolve } from 'path';
import { ICommand } from '../../../interface';
import { winToUnixPath } from '../../../util';

/**
 * 命令输入参数
 *
 * @export
 * @interface FileLogCommandOptions
 */
export interface FileLogCommandOptions {
	/**
	 * 当前目录
	 *
	 * @type {string}
	 */
	directory: string;

	/**
	 * 输出目录
	 *
	 * @type {string}
	 * @memberof FileLogCommandOptions
	 */
	output: string;

	/**
	 * 超级用户字符串
	 *
	 * @type {RegExp}
	 * @memberof FileLogCommandOptions
	 */
	supername: string;
}

/**
 * 运行模板编译
 *
 * @export
 * @class FileLogCommand
 * @implements {ICommand}
 */
export class FileLogCommand implements ICommand {
	load(program: Command): void {
		program
			.command('log')
			.description('过滤当前目录指定规则所有文件')
			.option('-d, --directory <directory-path>', '当前目录')
			.option('-o, --output <output-path>', '输出目录, 默认输出: 当前目录/user')
			.option('-s  --supername <supername-str>', '超级用户名(排除此用户)')
			.action(this.action.bind(this));
	}

	/**
	 * 计算非超级用户的提交文件及最后提交人
	 *
	 * @param {string[]} outputPaths
	 * @memberof FileLogCommand
	 */
	computedUser(supername: string, outputPaths: string[]) {
		const result: Array<any> = [];
		if (outputPaths && outputPaths.length > 0) {
			outputPaths.forEach((path: string) => {
				const authors = execSync(`git log --format=%an ${path}`)
					.toString()
					.trim();
				if (authors && authors.length > 0) {
					const author = authors.split('\n')[0];
					if (author && author !== supername) {
						result.push({ path, author });
					}
				}
			});
		}
		return result;
	}

	/**
	 * 写git报告文件
	 *
	 * @memberof FileLogCommand
	 */
	writeGitReportFile(outputPath: string, result: Array<any>) {
		writeFileSync(
			outputPath,
			`
			<!DOCTYPE html>
			<html lang="en">
				<head>
					<meta charset="UTF-8" />
					<meta name="viewport" content="width=device-width, initial-scale=1.0" />
					<title>GIT自定义提交记录报告</title>
					<style>
					.page-header {
						display: flex;
						align-items: center;
						justify-content: space-between;
						height: 70px;
					}
					.search-container select {
						width: 200px;
						height: 32px;
					}
					.page-content{
						height: calc(100vh - 86px);
						overflow-y: auto;
					}
					table.table-container {
						border-collapse: collapse;
						width: 100%;
						margin-bottom: 4px;
						margin-top: 4px;
					}
		
					table.table-container .fa {
						font-size: 24px;
					}
		
					table.table-container tr:nth-child(odd) {
						background-color: #f6f4f0;
					}
		
					table.table-container tr:nth-child(even) {
						background-color: #fff;
					}
		
					table.table-container tr.fixzebra {
						background-color: #f6f4f0;
					}
		
					table.table-container th {
						color: #fff;
						background-color: #555;
						border: 1px solid #555;
						font-size: 13px;
						padding: 3px;
						vertical-align: top;
						text-align: left;
					}
		
					table.table-container th a:link,
					table.table-container th a:visited {
						color: #fff;
					}
		
					table.table-container th a:active,
					table.table-container th a:hover {
						color: #ee872a;
					}
		
					tr td:first-child {
						min-width: 25px;
					}
		
					table.table-container td {
						line-height: 2em;
						min-width: 24px;
						border: 1px solid #d4d4d4;
						padding: 5px;
						padding-top: 7px;
						padding-bottom: 7px;
						vertical-align: top;
					}
		
					table.table-container td.example_code {
						vertical-align: bottom;
					}
					</style>
				</head>
				<body>
					<div class="page-header">
						<h2>GIT自定义提交记录报告</h2>
						<div class="search-container">
							<select onchange="checkField(this.value)">
								<option value="all">全部</option>
								${this.getAllAuthorOptionStr(result)}
							</select>
						</div>
					</div>
					<div class="page-content">
						<table class="table-container" id="table">
							<tbody>
								<tr><th style="width: 60%">文件路径</th><th>最后提交人</th></tr>
								${this.getAllLogInfoStr(result)}
							</tbody>
						</table>
					</div>
					<script>
						function getAllData() {
							return ${JSON.stringify(result)};
						}
						function checkField(value) {
							const result = getAllData();
							let returnStr ='<tbody><tr><th style="width: 60%">文件路径</th><th>最后提交人</th></tr>'
							result.forEach((item) =>{
								if (value === 'all') {
									returnStr += '<tr><td><a>'+item.path+'</a></td><td>'+item.author+'</td></tr>';
								}else{
									if(item.author === value){
										returnStr += '<tr><td><a>'+item.path+'</a></td><td>'+item.author+'</td></tr>';
									}
								}
							})
							returnStr +='</tbody>';
							document.getElementById('table').innerHTML = returnStr;
						}
					</script>
				</body>
			</html>
		`
		);
	}

	/**
	 * 获取所有作者
	 *
	 * @memberof FileLogCommand
	 */
	getAllAuthorOptionStr(result: Array<any>) {
		let returnStr = '';
		const tempArray: Array<string> = [];
		if (result && result.length > 0) {
			result.forEach((item: any) => {
				if (tempArray.indexOf(item.author) === -1) {
					tempArray.push(item.author);
				}
			});
			if (tempArray.length > 0) {
				tempArray.forEach((author: string) => {
					returnStr += `<option value="${author}">${author}</option>`;
				});
			}
		}
		return returnStr;
	}

	/**
	 * 获取所有自定义提交日志记录
	 *
	 * @param {Array<any>} result
	 * @memberof FileLogCommand
	 */
	getAllLogInfoStr(result: Array<any>) {
		let returnStr = '';
		if (result && result.length > 0) {
			result.forEach((item: any) => {
				returnStr += `<tr><td><a>${item.path}</a></td><td>${item.author}</td></tr>`;
			});
		}
		return returnStr;
	}

	/**
	 * 执行行为
	 *
	 * @param {FileLogCommandOptions} options
	 * @return {*}  {Promise<void>}
	 * @memberof FileLogCommand
	 */
	async action(options: FileLogCommandOptions): Promise<void> {
		let { directory, output, supername } = options;
		const curFolder = normalize(resolve(directory));
		if (!output) {
			output = `${directory}/user`;
		}
		const outputFolder = normalize(resolve(output));
		const curFolderWin = winToUnixPath(curFolder);
		const outputFolderWin = normalize(resolve(outputFolder));
		const outputPaths = glob.sync(`${curFolderWin}/**`, {
			nodir: true,
			ignore: [`${curFolderWin}/node_modules/**`, `${curFolderWin}/dist/**`],
		});
		const result = this.computedUser(supername, outputPaths);
		await Promise.all(
			result.map((file) => {
				const outFilePathStr =
					outputFolderWin + file.path.replace(curFolderWin, '');
				return cpFile(file.path, outFilePathStr);
			})
		);
		const outFilePathStr = outputFolderWin + '/git-report.html';
		this.writeGitReportFile(outFilePathStr, result);
		process.exit();
	}
}
